package com.spic.business.informatization.before_after_work.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.huawei.sis.bean.AuthInfo;
import com.huawei.sis.bean.SisConfig;
import com.huawei.sis.bean.SisConstant;
import com.huawei.sis.bean.request.AsrCustomLongRequest;
import com.huawei.sis.bean.response.AsrCustomLongResponse;
import com.huawei.sis.client.AsrCustomizationClient;
import com.huawei.sis.exception.SisException;
import com.huawei.sis.util.JsonUtils;
import com.spic.business.informatization.before_after_work.domain.MeetingBeforeAfter;
import com.spic.business.informatization.before_after_work.mapper.MeetingBeforeAfterMapper;
import com.spic.business.two.tickets.general.eum.TableCategoryEnum;
import com.spic.common.core.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Description 文件文本检索服务
 * @Author AnQi
 * @Date 2021/11/11
 */
@Service
@Slf4j
public class AsyncService {


    @Autowired
    private MeetingBeforeAfterMapper meetingBeforeAfterMapper;


    private static final long TIMEOUT = 2400000; // 设置超时为40分钟

    private String ak = "TRTFDQ4IHEHFD7IWEDGN";
    private String sk = "WauKM77lBMQd5dsq8X0FZBO0RkNhhEej2OD1bsVP";
    private String region = "cn-north-4";    // 区域，如cn-north-1、cn-north-4
    private String projectId = "0c9c33ad4e00f4d72f9ac00fc803165e"; // 项目id。登录管理控制台，鼠标移动到右上角的用户名上，在下拉列表中选择我的凭证，在项目列表中查看项目id。多项目时，展开“所属区域”，从“项目ID”列获取子项目ID。
    public static final String CATEGORY_NAME = TableCategoryEnum.MEETINGWORK.getCode();
    /**
     * todo 请正确填写音频格式和模型属性字符串
     * 1. 音频格式一定要相匹配.
     * 例如obs url是xx.wav, 则在录音文件识别格式是auto。
     * 例如音频是pcm格式，并且采样率为8k，则格式填写pcm8k16bit。
     * 如果返回audio_format is invalid 说明该文件格式不支持。
     * <p>
     * 2. 音频采样率要与属性字符串的采样率要匹配。
     * 例如格式选择pcm16k16bit，属性字符串却选择chinese_8k_common, 则属于采样率不匹配
     * 例如wav本身是16k采样率，属性选择chinese_8k_common, 同样属于采样率不匹配
     * <p>
     * 3. 用户可以通过使用热词，识别专业术语，增加语句识别准确率。
     */

    // 录音文件识别参数
    private String obsAudioFormat = "auto";   // 文件格式，如auto等
    private String obsProperty = "chinese_8k_common";      // 属性字符串，如chinese_8k_common等


    @Async("asyncGetVedioText")
    public void getVedioText(String url,String id) {

        String job = this.GetJobId(url);

        long start = System.currentTimeMillis();
        while (true) {
            String data = this.getText(job);
            MeetingBeforeAfter meetingBeforeAfter = meetingBeforeAfterMapper.selectMeetingBeforeAfterById(id, CATEGORY_NAME);
            if (data != null && !data.isEmpty() && meetingBeforeAfter !=null) {
                meetingBeforeAfter.setVedioResult(data);
                meetingBeforeAfterMapper.updateById(meetingBeforeAfter);
                return;
            }
            long elapsed = System.currentTimeMillis() - start;
            if (elapsed >= TIMEOUT) {
                return;
            }
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                break;
            }
        }
    }


    private String GetJobId(String obsUrl) {
        try {
            // 1. 初始化AsrCustomizationClient
            // 定义authInfo，根据ak，sk，region,projectId.
            AuthInfo authInfo = new AuthInfo(ak, sk, region, projectId);
            // 设置config，主要与超时有关
            SisConfig config = getConfig();
            // 根据authInfo和config，构造AsrCustomizationClient
            AsrCustomizationClient asr = new AsrCustomizationClient(authInfo, config);

            // 音频文件OBS链接，录音文件识别目前仅支持传入OBS音频连接，或公网可访问url
            //String obsUrl = "http://111.202.164.187:9000" + url;
            // 2. 生成请求
            AsrCustomLongRequest request = new AsrCustomLongRequest(obsUrl, obsAudioFormat, obsProperty);
            // 设置请求参数，所有参数均为可选
            setLongParameter(request);

            // 3. 提交任务，获取jobId
            String jobId = asr.submitJob(request);

            return jobId;

        } catch (SisException e) {

            throw new ServiceException("error_code:" + e.getErrorCode() + "\nerror_msg:" + e.getErrorMsg());
        }
    }


    private void setLongParameter(AsrCustomLongRequest request) {
        // 设置否是添加标点，yes 或no， 默认是no
        request.setAddPunc("yes");
        // 设置是否将语音中的数字转写为阿拉伯数字，yes或no，默认yes
        request.setDigitNorm("no");
        // 设置声道，MONO/LEFT_AGENT/RIGHT_AGENT, 默认是单声道MONO
        request.setChannel("MONO");
        // 设置是否需要分析，默认为false。当前仅支持8k采样率音频。当其设置为true时，话者分离、情绪检测，速度、声道才生效。
        request.setNeedAnalysis(true);
        // 设置是否需要话者分离，若是，则识别结果包含role，默认true
        request.setDirization(true);
        // 设置是否需要情绪检测，默认true。
        request.setEmotion(true);
        // 设置是否需要速度。默认true。
        request.setSpeed(true);
        // 设置回调地址，设置后音频转写结果将直接发送至回调地址。请务必保证地址可联通,不支持ip地址。
        // request.setCallbackUrl("");
        // 设置热词id，不使用则不用填写
        // request.setVocabularyId("");
    }

    private SisConfig getConfig() {
        SisConfig config = new SisConfig();
        // 设置连接超时，默认10000ms
        config.setConnectionTimeout(SisConstant.DEFAULT_CONNECTION_TIMEOUT);
        // 设置读取超时，默认10000ms
        config.setReadTimeout(SisConstant.DEFAULT_READ_TIMEOUT);
        // 设置代理, 一定要确保代理可用才启动此设置。 代理初始化也可用不加密的代理，new ProxyHostInfo(host, port);
        // ProxyHostInfo proxy = new ProxyHostInfo(host, port, username, password);
        // config.setProxy(proxy);
        return config;
    }


    public String getText(String jobId){
        try
        {
            AuthInfo authInfo = new AuthInfo(ak, sk, region, projectId);
            // 设置config，主要与超时有关
            SisConfig config = getConfig();
            // 根据authInfo和config，构造AsrCustomizationClient
            AsrCustomizationClient asr = new AsrCustomizationClient(authInfo, config);

            // 4 轮询jobId，获取最终结果。
            AsrCustomLongResponse response = null;
            response = asr.getAsrLongResponse(jobId);
            String status = response.getStatus();
            if (status.equals("FINISHED"))
            {
                String jsonStr = null;
                jsonStr = JsonUtils.obj2Str(response, true);

                System.out.println(jsonStr);
                JSONObject jsonObject = JSONObject.parseObject(jsonStr);
                JSONArray segments = jsonObject.getJSONArray("segments");
                if (segments != null && segments.size() > 0)
                {
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < segments.size(); i++)
                    {
                        JSONObject segment = (JSONObject) segments.get(i);
                        sb.append(segment.getJSONObject("result").getString("text"));
                    }
                    return sb.toString();
                }
            }
        }catch (SisException e)
        {
            e.printStackTrace();
        }
        return "";
    }
}
